#include "ibp_util.h"

char *StrdupEntireFile( char *pathfilename , int *p_file_len )
{
	char		*file_content = NULL ;
	int		file_len ;
	FILE		*fp = NULL ;
	
	int		nret = 0 ;
	
	fp = fopen( pathfilename , "rb" ) ;
	if( fp == NULL )
	{
		return NULL;
	}
	
	fseek( fp , 0 , SEEK_END );
	file_len  = ftell( fp ) ;
	fseek( fp , 0 , SEEK_SET );
	
	file_content = (char*)malloc( file_len+1 ) ;
	if( file_content == NULL )
	{
		fclose( fp );
		return NULL;
	}
	memset( file_content , 0x00 , file_len+1 );
	
	nret = fread( file_content , 1 , file_len , fp ) ;
	if( nret != file_len )
	{
		fclose( fp );
		free( file_content );
		return NULL;
	}
	
	fclose( fp );
	
	if( p_file_len )
		(*p_file_len) = file_len ;
	return file_content;
}

int WriteEntireFile( char *pathfilename , char *file_content , int file_len )
{
	FILE		*fp = NULL ;
	size_t		size ;
	
	fp = fopen( pathfilename , "wb" ) ;
	if( fp == NULL )
	{
		return -1;
	}
	
	size = fwrite( file_content , 1 , file_len , fp ) ;
	if( size != file_len )
	{
		fclose( fp );
		return -2;
	}
	
	fclose( fp );
	
	return 0;
}

int Md5File( char *pathfilename , char *md5_result_exp )
{
	char	*file_content = NULL ;
	int	file_len ;
	char	md5_result[ MD5_DIGEST_LENGTH + 1 ] ;
	
	file_content = StrdupEntireFile( pathfilename , & file_len ) ;
	if( file_content == NULL )
		return -1;
	
	memset( md5_result , 0x00 , sizeof(md5_result) );
	MD5( (unsigned char*)file_content , file_len , (unsigned char*)md5_result );
	
	free( file_content );
	
	memset( md5_result_exp , 0x00 , MD5_DIGEST_LENGTH*2+1 );
	HexExpand( md5_result , MD5_DIGEST_LENGTH , md5_result_exp );
	
	return 0;
}

void Md5Data( char *data , int data_len , char *md5_result_exp )
{
	char	md5_result[ MD5_DIGEST_LENGTH + 1 ] ;
	
	memset( md5_result , 0x00 , sizeof(md5_result) );
	MD5( (unsigned char*)data , data_len , (unsigned char*)md5_result );
	
	memset( md5_result_exp , 0x00 , MD5_DIGEST_LENGTH*2+1 );
	HexExpand( md5_result , MD5_DIGEST_LENGTH , md5_result_exp );
	
	return;
}

/* These are the characters used in temporary filenames.  */
static const char letters[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

/* Generate a temporary file name based on TMPL.  TMPL must match the
   rules for mk[s]temp (i.e. end in "XXXXXX").  The name constructed
   does not exist at the time of the call to mkstemp().  TMPL is
   overwritten with the result.  Creates the file and returns a read-write
   fd; the file is mode 0600 modulo umask.

   We use a clever algorithm to get hard-to-predict names. */
int _mkstemp (char *tmpl) {
  int len;
  char *XXXXXXXXXX;
  static uint64_t value;
  struct timeval tv;
  int count, fd;
  int save_errno = errno;

  len = strlen (tmpl);
  if (len < 10+4 || strncmp (&tmpl[len-4-10], "XXXXXXXXXX" , 10 ) )
    {
      errno = EINVAL;
      return -1;
    }

  /* This is where the Xs start.  */
  XXXXXXXXXX = &tmpl[len-4-10] ;

  /* Get some more or less random data.  */
  gettimeofday (&tv, NULL);
  value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();

  for (count = 0; count < TMP_MAX; value += 7777, ++count)
    {
      uint64_t v = value;

      /* Fill in the random bits.  */
      XXXXXXXXXX[0] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[1] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[2] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[3] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[4] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[5] = letters[v % 62];

      value += 7777 ;
      v = value ;
      
      /* Fill in the random bits.  */
      XXXXXXXXXX[6] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[7] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[8] = letters[v % 62];
      v /= 62;
      XXXXXXXXXX[9] = letters[v % 62];

/* NOTE: this, or test for _LARGEFILE_SOURCE in order to use the O_LARGEFILE
 *  open flag
 */

#ifdef _LARGEFILE_SOURCE
      fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, 0777);
#else
      fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, 0777);
#endif
      if (fd >= 0)
	{
          errno = save_errno;
          return fd;
        }
      else if (errno != EEXIST)
        /* Any other error will apply also to other names we might
           try, and there are 2^32 or so of them, so give up now. */
        return -1;
    }

  /* We got out of the loop because we ran out of combinations to try.  */
  errno = EEXIST;
  return -1;
}

FILE *IBPCreateTempFile( char *file_id , char *filename , char *pathfilename , char *mode )
{
	int	file_id_len ;
	char	buffer[ 256 + 1 ] ;
	int	fd ;
	
	memset( buffer , 0x00 , sizeof(buffer));
	file_id_len = strlen(file_id) ;
	sprintf( buffer , "%s/file/%.*s_XXXXXXXXXX.tmp" , getenv("HOME") , file_id_len , file_id );
	fd = _mkstemp( buffer ) ;
	if( fd < 0 )
		return NULL;
	
	if( filename )
		strcpy( filename , buffer + strlen(buffer) - file_id_len - 1 - 10 - 4 );
	if( pathfilename )
		strcpy( pathfilename , buffer );
	
	return (FILE*)fdopen( fd , mode );
}

char *TrimFileId( char *filename )
{
	char	*p = NULL ;
	
	p = strchr( filename , '_' ) ;
	if( p == NULL )
		return NULL;
	(*p) = '\0' ;
	
	return filename;
}

